﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using Templates.SharpParts.Logic.Model.Enum;

namespace Templates.SharpParts.Shells
{
	public partial class MethodShell
	{
		public string ReturnBody { get; set; }

		private string ReturnString
		{
			get
			{
				string result;

				if (ReturnType == CsType.Void && string.IsNullOrWhiteSpace(ReturnBody))
				{
					result = string.Empty;
				}
				else if (ReturnType != CsType.Void && !string.IsNullOrWhiteSpace(ReturnBody))
				{
					result = string.Format("return {0};", ReturnBody.Trim());
				}
				else
				{
					throw new ApplicationException("Method return type and return body doesn't match");
				}
				return result;
			}
		}


		private string ArgsString
		{
			get
			{
				StringBuilder sb = new StringBuilder();
				if (Args != null)
				{
					var list = Args.ToList();
					for (int i = 0; i < list.Count; i++)
					{
						sb.AppendFormat("{0} {1}", list[i].GetTypeString(), list[i].Name);
						if ((i + 1) < list.Count)
							sb.Append(", ");
					}
				}
				return sb.ToString();
			}
		}

		public IEnumerable<MethodArg> Args { get; set; }

		public string MethodName { get; set; }
		public CsType ReturnType { get; set; }

		public CsAccessor CsAccessor { get; set; }
		public string Body { get; set; }


		public override int GetHashCode()
		{
			return string.Format("{0}{1}", MethodName, IEnumerableExtention.ToString(Args)).GetHashCode();
		}

	}

	public class MethodArg
	{
		public CsType Type { get; set; }
		public String Name { get; set; }
		public string CustomType { get; set; }

		public string GetTypeString()
		{
			if (this.Type != CsType.Custom)
				return T4TypeExtention.ToString(this.Type);
			else if (!string.IsNullOrWhiteSpace(CustomType))
				return CustomType.Trim();
			else
				throw new ApplicationException("Custom Type couldn't be empty for Type.Custom");
		}

		public override string ToString()
		{
			return string.Format("{0} {1}", GetTypeString(), Name);
		}
	}

	[AttributeUsageAttribute(AttributeTargets.Method, AllowMultiple = false)]
	public class OverrideAttribute : Attribute {}

	public static class T4AccessorExtention
	{
		[Override]
		public static string ToString(this CsAccessor type)
		{
			switch (type)
			{
				case CsAccessor.Public:
					return "public";
				case CsAccessor.Internal:
					return "internal";
				case CsAccessor.Protected:
					return "protected";
				case CsAccessor.Private:
					return "private";
				default:
					throw new ArgumentOutOfRangeException("type");
			}
		}
	}

	public static class T4TypeExtention
	{
		[Override]
		public static string ToString(this CsType type)
		{
			switch(type)
			{
				case CsType.String:
					return "string";
				case CsType.Int32:
					return "int";
				case CsType.Void:
					return "void";

				default:
					throw new ArgumentOutOfRangeException("type");
			}
		}
	}

	public static class IEnumerableExtention
	{
		public static string ToString<T>(this IEnumerable<T> col)
		{
			string result = string.Empty;

			foreach (T item in col)
				result += item;

			return result;
		}
	}
}
